<?php

namespace app\common\model;

use think\Model;
use app\common\model\Rsa;

/**
 * @Author: qian 
 * @Date:   2019-11-11 09:21:40
 * @Last Modified by:   qian
 * @Last Modified time: 2020-01-13 09:31:12
 */
/**
 * 
 */
date_default_timezone_set("PRC");

class Huichao
{
    private static $accountNumber = '50326';
    private static $accountNumberWx = '372134343';

    // 下发秘钥 商户私钥  并且不能出现空格等多余字符【别用成交易秘钥】
    private static $prikey = 'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJSSptZa2TloE1Wikp5mIsAYmf3gSOVk+MCNnzOf1TMmrf7paZIAbNaE+5DcwAkj8SmFD5wipJJqsjqFhVil+Yn+AzcVBM9zTGKG9BwEOcXvZkfA0SReNT4lyh7TP4oxqCrwB8xwxv5Df33VFo2PLHARxf8/cobcJMHPYOqV9HDTAgMBAAECgYAOjCF74Z9daJxkCSwUCGokpwQFAL4CgBV/PR62flLw1Du7Nv2YRyRhCNpc/9Bp1LQbXaT+o8G7eGkFI+e/m1jIi8cqejnmucqOdLvMCbg5Y8ABWEffrAQEP/KvpDAybCsy6ipcMKYqGdYmSqDqNxltZlZhFJOCEg1v0qkoJ1MmaQJBAPrXbzrARpWu6S9alhAdnsSCiQgXr4ijesegb/iJd/WZhCViFbw3KmQsJKdi3FK3fbLiwG5ZzCumdIJy4BNYfB8CQQCXoNHPezD9zGEnoxEpwcnldVCF2c/05gx0gYvK4TZS+LTcEe6Ys59fLQuDgXjTT3djAW2xrTBk9CdltHEExXTNAkEApR8NzEnn7P6f55kk8WTeL5OSKu6UkUi0ORbGvn+XpOeykn03u5dA44IfesRcLmM1bn1PmRSpjw5a4chG8tUrlwJADv83AUB7/f5C9bqpLeoe3/UUe8ipSt2eCb/uZaiUyOwUZ1fWs3/AmZdI9j7OBohrlH1Frjck/Dcx1ltcek5VWQJBAME3TewBnnUc87CUp3Jwt105Gq33OfkeCKCUDC++ZE+hhBtM/AO4GkRP2yqoMEiCdnDRzCDRgJzolXLC5V3F3bA=';
    // 下发秘钥 一麻袋公钥   并且不能出现空格等多余字符
    private static $pubkey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOGrUM5kcF0urwTV6JbhGitJLNNmQ6YA17oc7M83MAcAB+nOARQIX9z1DSjEWr/l8NrEUjF4ee8c9Z3KvCuCuJexVH5aSsZR56IljxBaW2RRPlIf0JUBCuWbyznfMVraxnsdFETwKahKSa53AlFl1Kd4V+r6I/D5OJlptNbCegfQIDAQAB';

    // 一麻袋请求域名
    const URL = 'https://gwapi.yemadai.com/';

    // 一麻袋分账域名
    const FZ_URL = 'https://fzapi.yemadai.com/';
    // 异步通知自己服务器通知地址
    const NOTIFY_URL = '';
    // 网关支付同步返回
    const RETURN_URL = '';

    const AESKEY = "hmFEPce/ceneP+sGxh0s3w==";

    //子商户入网
    public function spNetwork($oneRecord)
    {
        if ($oneRecord['subMerType'] == 3) { // 个人
            $channel = 'pernetwork';
        } else {  //企业
            $channel = 'network';
        }

        $requestData = [
            'total' => '1',
            'backURL' => self::NOTIFY_URL . '?channel=' . $channel,
        ];
        //子商户数据集
        $requestData['data'][] = $oneRecord;

        $data = $this->makeData($requestData);

        $url = self::FZ_URL . 'sp/' . $channel;
        // dump($data);exit;
        return $this->curl_post($url, $data);
    }


    //微信进件
    public function wechatInCase($PayType)
    {
        $RandomStr = substr(md5(time() . microtime()), 0, 9);
        $rsa = new Rsa();
        $sign = "MerNo=".self::$accountNumber."&PayType=".$PayType."&RandomStr=".$RandomStr;
        $SignInfo = $rsa->privEncrypt($sign);

        $str = '<?xml version="1.0" encoding="utf-8" ?>';
        $str .= '<ScanMerchantInRequest>';
        $str .= '<MerNo>50326</MerNo>';
        $str .= '<Version>1.0</Version>';
        $str .= '<PayType>'.$PayType.'</PayType>';
        $str .= '<SignInfo>'.$SignInfo.'</SignInfo>';
        $str .= '<RandomStr>'.$RandomStr.'</RandomStr>';
        $str .= '<ChannelNo>372134343</ChannelNo>';
        $str .= '<MerchantInfo>';
        $str .= '<MerName>山陆久（上海）汽车科技有限公司</MerName>';
        $str .= '<ShortName>山陆久</ShortName>';
        $str .= '<ServicePhone>02169171010</ServicePhone>';
        $str .= '<Business>95</Business>';
        $str .= '<SubAppID>wx33ce2dbde6f86814</SubAppID>';
        $str .= '</MerchantInfo>';
        $str .= '</ScanMerchantInRequest>';
        $url = self::URL . 'scanpay/merchantIn';
        // echo $str;exit;
        $data = 'requestDomain=' . base64_encode($str);

        return $this->curl_post($url, $data);
    }

    //签名
    private function sign1($data)
    {
        return $this->_reaEncode($data);
    }

    // RSA加密
    private function _reaEncode($str)
    {
        $prikey = self::_redPrikey();

        return openssl_sign($str, $sign, $prikey, OPENSSL_ALGO_SHA1) ? base64_encode($sign) : false;
    }

    private function _redPrikey()
    {
        $pem = "-----BEGIN RSA PRIVATE KEY-----\n" . chunk_split(self::$prikey, 64, "\n") . "-----END RSA PRIVATE KEY-----\n";
        return openssl_pkey_get_private($pem);
    }




    //分账系统组装数据   （加密规则）
    private function makeData($data)
    {
        $requestTime = date('YmdHis');

        $jsonCode = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        $baseCont = base64_encode($jsonCode);
        $AESKey = $this->generateAESKey();
        // $AESKEY = $this->pkcs5_pad($AESKey, 16);
        // echo $AESKey;exit;
        $requestData = $this->encrypt($baseCont, $AESKey);
        // echo '解析前base'.$baseCont;
        // echo '<br/>';
        $a = $this->decrypt($requestData, $AESKey);
        // echo '解析后base'.$a;

        // $encryptKey = $this->publicEncrypt($AESKey);
        $rsa = new Rsa();
        $encryptKey = $rsa->publicEncrypt(base64_encode($AESKey));

        // sign的组成部分：按照requestData+requestTime+merchantNo的顺序将此三个参数拼接起来然后进行Base64加密得到密文，将此【密文】和【商户的私钥】进行RSA签名，签名后的密文后赋值给sign参数。
        $sign = $rsa->privEncrypt(base64_encode($requestData . $requestTime . self::$accountNumber));

        $out = [
            'requestTime' => $requestTime, //请求时间
            'version' => '1.0', //版本
            'merchantNo' => self::$accountNumber, //平台商户号
            'requestData' => $requestData, //业务数据AES解密后的结果
            'encryptKey' => $encryptKey, //对称密钥AES Key使用麻袋公钥加密后的结果
            'sign' => $sign, //签名 下面是新加的
            'amount' => 100,
            // 'merchantOrderNo'=>$data['scanpayMerchantCode'],
            // 'payType' => 'WxJsapi_OnLine',
            // 'remark' => '测试',
        ];
        // dump($out);exit;
        return $out;
    }

    //聚合支付
    public function getPayInfo($url, $requestData)
    {
        $rsa = new Rsa();

        //同步响应结果签名约定 签名
        $message = "成功";
        $tong_sign = "merchantNo=" . self::$accountNumber . "&merchantOrderNo=" . $requestData['merchantOrderNo'] . "&amount=" . $requestData['amount'] . "&code=" . "SUCCESS" . "&message=" . $message;
        $TongSign = $rsa->privEncrypt($tong_sign);

        //异步通知签名约定
        $Yi_sign = "merchantNo=" . self::$accountNumber . "&merchantOrderNo=" . $requestData['merchantOrderNo'] . "&orderNo=" . 'GW8419237498172394' . "&amount=" . $requestData['amount'] . "&code=" . "SUCCESS" . "&message=" . $message;
        $yiSign = $rsa->privEncrypt($Yi_sign);


        //加密规则
        $data = $this->makeData($requestData);
        //发送请求
        return $this->curl_post($url, $data);
    }

    //判断是否入驻成功了。
    public function getSettledInfo($PayType, $companyNo)
    {
        $RandomStr = substr(md5(time() . microtime()), 0, 9);
        $rsa = new Rsa();
        $sign = "MerNo=" . self::$accountNumber . "&CompanyNo=" . $companyNo . "&PayType=" . $PayType . "&RandomStr=" . $RandomStr;
        $SignInfo = $rsa->privEncrypt($sign);

        $str = '<?xml version="1.0" encoding="utf-8" ?>';
        $str .= '<ScanMerchantInRequest>';
        $str .= '<MerNo>' . self::$accountNumber . '</MerNo>';
        $str .= '<Version>1.0</Version>';
        $str .= '<PayType>' . $PayType . '</PayType>';
        $str .= '<SignInfo>' . $SignInfo . '</SignInfo>';
        $str .= '<RandomStr>' . $RandomStr . '</RandomStr>';
        $str .= '<CompanyNo>' . $companyNo . '</CompanyNo>';
        $str .= '</ScanMerchantInRequest>';
        $url = self::URL . 'scanpay/merchantInQuery';
        // echo $str;exit;
        $data = 'requestDomain=' . base64_encode($str);

        return $this->curl_post($url, $data);
    }



    /**
     * 加密
     * @param String input 加密的字符串
     * @param String key   解密的key
     * @return HexString
     */
    public function encrypt($input = '', $key = '')
    {
        // $key = base64_decode($key);
        //PKCS5Padding
        $input = $this->pkcs5_pad($input);
        $data = @mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $input, MCRYPT_MODE_ECB, "1");
        return base64_encode($data);
    }

    public function decrypt($sStr, $sKey)
    {
        // $sKey = base64_decode($sKey);
        $encryptedData = base64_decode($sStr);
        $decrypted = @mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $sKey, $encryptedData, MCRYPT_MODE_ECB, "1");
        $decrypted = $this->removePadding($decrypted);
        return $decrypted;
    }

    //删除填充符
    public function removePadding($str)
    {
        $len = strlen($str);
        $newstr = "";
        $str = str_split($str);
        for ($i = 0; $i < $len; $i++) {
            if (!in_array($str[$i], array(chr(0), chr(1), chr(2), chr(3), chr(4), chr(5), chr(6), chr(7), chr(8)))) {
                $newstr .= $str[$i];
            }
        }
        return $newstr;
    }

    /**
     * 生成随机AES密钥
     * @return string
     */
    public function generateAESKey()
    {
        //生成随机AES密钥
        $strRand = $this->create_string(16);
        return base64_encode($strRand);
    }

    public function create_string($strLen)
    {
        $randStr = "";
        for ($i = 0; $i < $strLen; $i++) {
            $randStr .= chr(mt_rand(33, 126));
        }
        return $randStr;
    }

    /**
     * 填充方式 pkcs5
     * @param String text        原始字符串
     * @param String blocksize   加密长度
     * @return String
     */
    private function pkcs5_pad($input)
    {
        $size = @mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
        $padding = $size - strlen($input) % $size;
        // 添加Padding
        $input .= str_repeat(chr($padding), $padding);
        return $input;
    }





    private function curl_post($posturl, $post, $header = array())
    {
        $ch = curl_init(); //打开
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 3);   //设置curl请求最长等待时间，单位：秒
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);    //请求Https时需要这两行配置
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        if (!empty($header)) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        }
        curl_setopt($ch, CURLOPT_URL, $posturl);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
        // dump($post);
        $result = curl_exec($ch);
        return $result;
    }
}
